﻿using System.Windows;
using Gavel.Common.Component.Helper;
using Gavel.Common.Utilities.Const;
using Gavel.Common.Utilities.Model;
using Gavel.ModLink.Helper;
using Gavel.ModLink.Model;
using Gavel.ModLink.ViewModel;

namespace Gavel.ModLink.Views;

/// <summary>
/// 寄存器配置视图
/// </summary>
public partial class OptionsView
{
    /// <summary>
    /// 寄存器配置视图模型
    /// </summary>
    private readonly OptionsViewModel _viewModel;

    /// <summary>
    /// 自动读取任务
    /// </summary>
    private Task? _autoRequestTask;

    /// <summary>
    /// 向取消标记发出取消信号
    /// </summary>
    private CancellationTokenSource? _cancellation;

    /// <summary>
    /// 是否正在自动读取
    /// </summary>
    private bool _isAutoRequesting;

    /// <summary>
    /// 默认构造
    /// </summary>
    public OptionsView()
    {
        InitializeComponent();
        _viewModel = (OptionsViewModel)DataContext;
        ClientHelper.Instance.SocketStatusChangedEvent += SocketStatusChanged;
        ClientHelper.Instance.ReceivedEvent += Received;
    }

    /// <summary>
    /// 套接字状态改变
    /// </summary>
    /// <param name="status">套接字状态</param>
    private void SocketStatusChanged(SocketStatus status)
    {
        _viewModel.IsAuto = status == SocketStatus.Connected && _viewModel.IsAuto;
        _viewModel.ShowSendView = status == SocketStatus.Connected ? Visibility.Visible : Visibility.Collapsed;
    }

    /// <summary>
    /// 发送数据请求
    /// </summary>
    /// <param name="sender">事件发送者</param>
    /// <param name="e">事件参数</param>
    private async void SendRequest(object sender, RoutedEventArgs e)
    {
        try
        {
            if (_viewModel.CanSend == false)
            {
                return;
            }

            _viewModel.CanSend = false;
            await Request();
        }
        catch (Exception exception)
        {
            NotifyHelper.Instance.Error($"数据读取异常\n{exception.Message}");
        }
        finally
        {
            _viewModel.CanSend = true;
        }
    }

    /// <summary>
    /// 启用自动请求
    /// </summary>
    /// <param name="sender">事件发送者</param>
    /// <param name="e">事件参数</param>
    private void EnableAutoRequest(object sender, RoutedEventArgs e)
    {
        if (_isAutoRequesting)
        {
            return;
        }

        _cancellation = new CancellationTokenSource();
        _isAutoRequesting = true;
        _autoRequestTask = Task.Run(async () =>
        {
            try
            {
                while (_cancellation?.Token.IsCancellationRequested == false)
                {
                    try
                    {
                        await Request();
                    }
                    catch (Exception exception)
                    {
                        NotifyHelper.Instance.Error($"自动读取异常\n{exception.Message}");
                    }
                    finally
                    {
                        await Task.Delay(TimeSpan.FromSeconds(_viewModel.Period.Key), _cancellation.Token);
                    }
                }

                Dispatcher.Invoke(() => _viewModel.IsAuto = false);
            }
            catch (OperationCanceledException)
            {
                NotifyHelper.Instance.Success("自动读取已停止");
            }
            catch (Exception exception)
            {
                NotifyHelper.Instance.Error($"自动读取异常\n{exception.Message}");
            }
            finally
            {
                _isAutoRequesting = false;
            }
        }, _cancellation.Token);
    }

    /// <summary>
    /// 停用自动请求
    /// </summary>
    /// <param name="sender">事件发送者</param>
    /// <param name="e">事件参数</param>
    private async void DisableAutoRequest(object sender, RoutedEventArgs e)
    {
        try
        {
            if (_isAutoRequesting == false || _cancellation is null)
            {
                return;
            }

            await _cancellation.CancelAsync();
            if (_autoRequestTask is not null)
            {
                await _autoRequestTask;
            }

            _cancellation.Dispose();
            _cancellation = null;
        }
        catch (Exception exception)
        {
            NotifyHelper.Instance.Error($"停止自动读取异常\n{exception.Message}");
        }
    }

    /// <summary>
    /// 发送请求
    /// </summary>
    private async Task Request()
    {
        RequestFrame frame = new RequestFrame(_viewModel.Protocol.Key, _viewModel.Function.Key, _viewModel.Slave, _viewModel.StartAddr, _viewModel.Count, _viewModel.Endian);
        MessageTransmit transmit = new MessageTransmit(frame.Protocol, frame.Function, TransmitWay.Request, frame.RegisterAddr, frame.Message);
        await ClientHelper.Instance.Send(transmit);
    }

    /// <summary>
    /// 接收到报文回复
    /// </summary>
    /// <param name="transmit">报文传输</param>
    private async void Received(MessageTransmit transmit)
    {
        try
        {
            if (transmit.Function is not (FunctionType.WriteSingle or FunctionType.WriteMultiple))
            {
                return;
            }

            byte code = transmit.Protocol switch
            {
                ProtocolType.Tcp => transmit.Data[7],
                _ => transmit.Data[1]
            };

            if (code > 80)
            {
                return;
            }

            await Request();
        }
        catch (Exception e)
        {
            NotifyHelper.Instance.Error(e.Message);
        }
    }
}